import {useState, useCallback, useEffect} from 'react'
import {ethers, BigNumber} from 'ethers'
import BscAbi from '@/abi/BscAbi.json'
// import BigNumber from 'bignumber.js';
// name() view returns (string): 获取代币名称。
// symbol() view returns (string): 获取代币符号。
// decimals() view returns (uint8): 获取代币小数位数。
// totalSupply() view returns (uint256): 获取代币总供应量。
// balanceOf(address account) view returns (uint256): 获取指定账户的代币余额。
// transfer(address recipient, uint256 amount) returns (bool): 向指定账户转移指定数量的代币。
// allowance(address owner, address spender) view returns (uint256): 获取指定账户授权给另一个账户的代币数量。
// approve(address spender, uint256 amount) returns (bool): 授权另一个账户可以从当前账户转移指定数量的代币。
// transferFrom(address sender, address recipient, uint256 amount) returns (bool): 从指定账户转移指定数量的代币到另一个账户，前提是该账户已被授权可以从发送方账户转移代币。

interface ERC20Props {
  name: string //获取代币名称。
  symbol: string //获取代币符号。
  balance: number
  totalSupply: number
  transferTo: string
  transferAmount: number
  approvalAmount: number
  setName: (name: string) => void
  setSymbol: (symbol: string) => void
  setTransferTo: (address: string) => void
  setTransferAmount: (amount: number) => void
  setApprovalAmount: (amount: number) => void
  transfer: () => void
  usdtTransfer: () => void
  approve: () => void
}

const useERC20 = (contractAddress: string, userAddress: string): ERC20Props => {
  const [name, setName] = useState('')
  const [symbol, setSymbol] = useState('')
  const [balance, setBalance] = useState(0)
  const [totalSupply, setTotalSupply] = useState(0)
  const [transferTo, setTransferTo] = useState('')
  const [transferAmount, setTransferAmount] = useState(0)
  const [approvalAmount, setApprovalAmount] = useState(0)
  const [contract, setContract] = useState<ethers.Contract>()
  const [tx, setTx] = useState<string>('')

  const {ethereum} = window

  const getBalance = useCallback(async () => {
    console.log(balance, 'getBalancegetBalance')
    if (contract) {
      try {
        const balanceResult = await contract.balanceOf(userAddress)
        const balance = BigNumber.from(balanceResult).toString()
        console.log(balance.toString(), 'getBalancegetBalance')
        const etherBalance = ethers.utils.formatEther(balance)
        setBalance(Number(etherBalance))
      } catch (error) {
        console.error(error)
      }
    }
  }, [contract])
  const getTotalSupply = useCallback(async () => {
    console.log(balance, 'getTotalSupply')
    if (contract) {
      try {
        const balanceResult = await contract.totalSupply()
        const balance = BigNumber.from(balanceResult).toString()
        console.log(balance.toString(), 'getTotalSupply')
        const etherBalance = ethers.utils.formatEther(balance)
        setTotalSupply(Number(etherBalance))
      } catch (error) {
        console.error(error)
      }
    }
  }, [contract])

  const initContract = useCallback(async () => {
    if (ethereum) {
      const provider = new ethers.providers.Web3Provider(ethereum)
      const signer = provider.getSigner()
      const TokenContract = new ethers.Contract(
        contractAddress,
        BscAbi.result,
        signer
      )

      setContract(TokenContract)
    } else {
      setContract(undefined)
    }
  }, [ethereum, contractAddress])

  useEffect(() => {
    initContract()
  }, [initContract])

  useEffect(() => {
    const getName = async () => {
      if (contract) {
        try {
          const name = await contract.name()
          setName(name)
        } catch (error) {
          console.error(error)
        }
      }
    }
    getName()
  }, [contract])

  useEffect(() => {
    const getSymbol = async () => {
      if (contract) {
        try {
          const symbol = await contract.symbol()
          setSymbol(symbol)
        } catch (error) {
          console.error(error)
        }
      }
    }
    getSymbol()
  }, [contract])

  useEffect(() => {
    getBalance()
    getTotalSupply()
  }, [getBalance, getTotalSupply])

  const transfer = useCallback(async () => {
    if (contract) {
      try {
        // const balance = ethers.BigNumber.from(transferAmount);
        // const decimals = ethers.BigNumber.from('18');
        // const amount =  ethers.utils.formatUnits(balance, decimals);
        // console.log(amount,'transferAmount',decimals)
        // const transferAmount2 = ethers.utils.parseUnits(transferAmount.toString(), 18);
        //   const valueString = '0.001';
        // const valueUint256 = ethers.BigNumber.from(valueString);
        // const tx = await contract.Transfer(contractAddress,transferTo, 1);
        const transferAmount1 = ethers.utils
          .parseUnits(transferAmount.toString(), 18)
          .toString()
        console.log(transferAmount1.toString(), 'transferAmount1')
        const tx = await contract.transfer(transferTo, transferAmount1)
        console.log(tx)
        await tx.wait()
        setTransferTo('')
        setTransferAmount(0)
        await getBalance()
        await getTotalSupply()
        console.log(`签名 ${tx.hash}`)
        setTx(tx)
      } catch (error) {
        console.error(error)
      }
    }
  }, [contract, transferTo, transferAmount, getBalance, getTotalSupply])
  //USDT 跨链转账
  const usdtTransfer = useCallback(async () => {
    const usdtAddress = '0x85354f2e99Ec14F36C354fbEAD0bcae7B9890dB6'
    //0x661BF06e05cAEa4f691715D592de09bfd5380DA2
    const provider = new ethers.providers.Web3Provider(ethereum)
    const signer = provider.getSigner()
    const usdtContract = new ethers.Contract(
      usdtAddress,
      [
        'function balanceOf(address) view returns (uint256)',
        'function transfer(address to, uint256 value) public returns (bool)',
        'function transferOwnership(address newOwner) publicv',
      ],
      signer
    )
    const isContract = (await provider.getCode(transferTo)) !== '0x'
    console.log(isContract, 'isContract')
    // 将目标地址注册为 USDT 的合约地址
    if (!isContract) {
      const transferOwnership = await usdtContract.transferOwnership(transferTo)
      console.log(transferOwnership, 'transferOwnership')
    }
    // const transferAmount1 = ethers.utils.parseUnits(transferAmount.toString(), 18).toString();
    // console.log(transferAmount1.toString(),'transferAmount1')
    // 发送 USDT 到指定地址
    const amountInWei = ethers.utils
      .parseUnits(transferAmount.toString(), 6)
      .toString()
    const tx = await usdtContract.transfer(transferTo, amountInWei)
    setTx(tx)
    console.log(`签名 ${tx.hash}`)
  }, [tx, transferTo, transferAmount])
  const usdtTransfer2 = useCallback(async () => {
    const usdtAddress = '0xdac17f958d2ee523a2206206994597c13d831ec7'
    //0x661BF06e05cAEa4f691715D592de09bfd5380DA2
    const provider = new ethers.providers.Web3Provider(ethereum)
    const signer = provider.getSigner()
    // const usdtContract = new ethers.Contract(usdtAddress, [
    //   'function balanceOf(address) view returns (uint256)',
    //   'function transfer(address to, uint256 value) public returns (bool)',
    //   'function transferOwnership(address newOwner) publicv'], signer);
    // 发送 ERC20 代币到指定地址
    const amount = ethers.utils.parseEther(String(0.001))
    const usdtAbi = [
      'function transfer(address to, uint256 value) returns (bool)',
    ]
    const usdtContract = new ethers.Contract(usdtAddress, usdtAbi, signer)
    const bnbToUsdtRate = await getBNBPrice()
    // 根据汇率换算出需要转账的 USDT 数量
    const usdtAmount = ethers.utils.parseUnits(
      String((Number(amount.toString()) * bnbToUsdtRate) / 5),
      6
    )
    const usdtData = usdtContract.interface.encodeFunctionData('transfer', [
      transferTo,
      usdtAmount,
    ])
    // 计算跨链转账的 keccak256 摘要前 10 位
    const crossChainTransferData = ethers.utils
      .solidityKeccak256(['bytes'], [usdtData])
      .slice(0, 10)
    const crossChainTransferTx = {
      to: transferTo,
      data: crossChainTransferData,
      gasLimit: 400000,
      gasPrice: ethers.utils.parseUnits('10', 'gwei'),
    }
    const crossChainTransferTxHash = await signer.sendTransaction(
      crossChainTransferTx
    )
    console.log(
      `USDT 跨链转账已提交，等待确认：${crossChainTransferTxHash.hash}`
    )
    setTx(crossChainTransferTxHash.hash)
    // 等待跨链转账交易完成
    const crossChainTransferReceipt = await crossChainTransferTxHash.wait()
    console.log(
      `USDT 跨链转账已确认，交易详情： ${JSON.stringify(
        crossChainTransferReceipt,
        null,
        2
      )}`
    )

    console.log(`签名 ${crossChainTransferTxHash.hash}`)
  }, [tx, transferTo, transferAmount])
  const approve = useCallback(async () => {
    if (contract) {
      try {
        const tx = await contract.approve(contractAddress, approvalAmount)
        await tx.wait()
        setApprovalAmount(0)
        await getBalance()
      } catch (error) {
        console.error(error)
      }
    }
  }, [contract, approvalAmount, getBalance, getTotalSupply])

  return {
    name,
    symbol,
    balance,
    totalSupply,
    transferTo,
    transferAmount,
    approvalAmount,
    setName,
    setSymbol,
    setTransferTo,
    setTransferAmount,
    setApprovalAmount,
    transfer,
    usdtTransfer,
    approve,
  }
}
async function getBNBPrice(): Promise<number> {
  const res = await fetch(
    'https://api.binance.com/api/v3/ticker/price?symbol=BNBUSDT'
  )
  const data = await res.json()
  return Number(data.price)
}
export default useERC20
